package com.netease.financial.data.repository;

import com.netease.financial.data.entity.AccessTokenCheckEntity;
import com.netease.financial.data.entity.AppUpdateEntity;
import com.netease.financial.data.entity.LaunchPageEntity;
import com.netease.financial.data.entity.LoginEntity;
import com.netease.financial.data.entity.LogoutEntity;
import com.netease.financial.data.entity.ActivityPageEntity;
import com.netease.financial.data.entity.PageInfoEntity;
import com.netease.financial.data.entity.RegisterEntity;
import com.netease.financial.data.entity.UnreadMessageCountEntity;
import com.netease.financial.data.entity.mapper.NfsEntityDataMapper;
import com.netease.financial.data.repository.datasource.NfsDataStore;
import com.netease.financial.data.repository.datasource.NfsDataStoreFactory;
import com.netease.financial.domain.interactor.RegisterInput;
import com.netease.financial.domain.model.AccessTokenCheck;
import com.netease.financial.domain.model.AppUpdate;
import com.netease.financial.domain.model.LaunchPage;
import com.netease.financial.domain.model.Login;
import com.netease.financial.domain.model.Logout;
import com.netease.financial.domain.model.ActivityPage;
import com.netease.financial.domain.model.PageInfo;
import com.netease.financial.domain.model.Register;
import com.netease.financial.domain.model.UnreadMessageCount;
import com.netease.financial.domain.repository.NfsRepository;

import java.util.List;

import javax.inject.Inject;

import rx.Observable;
import rx.functions.Func1;

/**
 * Created by wyf on 10/11/15.
 */
public class NfsDataRepository implements NfsRepository {

    private final NfsDataStoreFactory nfsDataStoreFactory;
    private final NfsEntityDataMapper nfsEntityDataMapper;

    /**
     * Constructs a {@link NfsRepository}.
     *
     * @param dataStoreFactory    A factory to construct different data source implementations.
     * @param nfsEntityDataMapper {@link NfsEntityDataMapper}.
     */
    @Inject
    public NfsDataRepository(NfsDataStoreFactory dataStoreFactory,
                             NfsEntityDataMapper nfsEntityDataMapper) {
        this.nfsDataStoreFactory = dataStoreFactory;
        this.nfsEntityDataMapper = nfsEntityDataMapper;
    }

    @Override
    public Observable<AppUpdate> getAppUpdateInfo(final String device, final int versionCode) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.create();
        return nfsDataStore.getAppUpdateInfo(device, versionCode).map(new Func1<AppUpdateEntity, AppUpdate>() {
            @Override
            public AppUpdate call(AppUpdateEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<UnreadMessageCount> getUnreadMessageCount(final String accessToken) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.getUnreadMessageCount(accessToken).map(new Func1<UnreadMessageCountEntity, UnreadMessageCount>() {
            @Override
            public UnreadMessageCount call(UnreadMessageCountEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<Login> login(String clientId, String clientSecret, String appSecret) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.login(clientId, clientSecret, appSecret).map(new Func1<LoginEntity, Login>() {
            @Override
            public Login call(LoginEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<Logout> logout(String accessToken, String appSecret) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();

        return nfsDataStore.logout(accessToken, appSecret).map(new Func1<LogoutEntity, Logout>() {
            @Override
            public Logout call(LogoutEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<AccessTokenCheck> checkAccessToken(String accessToken, String appSecret) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.checkAccessToken(accessToken, appSecret).map(new Func1<AccessTokenCheckEntity, AccessTokenCheck>() {
            @Override
            public AccessTokenCheck call(AccessTokenCheckEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<ActivityPage> getActivityPageInfo() {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.getActivityPageInfo().map(new Func1<ActivityPageEntity, ActivityPage>() {
            @Override
            public ActivityPage call(ActivityPageEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<LaunchPage> getLaunchPageInfo(int widthPixels, int heightPixels, String platform) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.getLaunchPageInfo(widthPixels, heightPixels, platform).map(new Func1<LaunchPageEntity, LaunchPage>() {
            @Override
            public LaunchPage call(LaunchPageEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<Register> register(RegisterInput registerInput) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.register(registerInput).map(new Func1<RegisterEntity, Register>() {
            @Override
            public Register call(RegisterEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

    @Override
    public Observable<PageInfo> getPageInfo(String pageName, List<String> elements, int widthPixels, int heightPixels, String platform) {
        final NfsDataStore nfsDataStore = this.nfsDataStoreFactory.createCloudDataStore();
        return nfsDataStore.getPageInfo(pageName, elements, widthPixels, heightPixels, platform).map(new Func1<PageInfoEntity, PageInfo>() {
            @Override
            public PageInfo call(PageInfoEntity entity) {
                return NfsDataRepository.this.nfsEntityDataMapper.transform(entity);
            }
        });
    }

}
